package com.polaris.live.utils

import android.Manifest
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.Settings
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.LifecycleOwner
import com.blankj.utilcode.util.ActivityUtils
import com.blankj.utilcode.util.PermissionUtils
import com.blankj.utilcode.util.StringUtils
import com.lxj.xpopup.XPopup
import com.polaris.live.common.cacha.UserManager
import com.polaris.live.common.constant.AppConst
import com.polaris.live.common.constant.CommonConst
import com.polaris.live.common.manager.CoroutineScopeManager
import com.polaris.live.common.mvvm.viewmodel.BaseViewModel
import com.polaris.live.common.network.AppException
import com.polaris.live.common.network.HTTP_ERROR_CODE
import com.polaris.live.common.network.launchLoading
import com.polaris.live.common.network.request
import com.polaris.live.common.network.requestLoading
import com.polaris.live.common.network.state.ResultState
import com.polaris.live.common.util.JsonUtils
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.constant.LiveConst
import com.polaris.live.constant.LiveConst.LiveType
import com.polaris.live.constant.LiveConst.PartyGameType
import com.polaris.live.constant.UserConst
import com.polaris.live.dialog.StartLiveLevelNotDialog
import com.polaris.live.dialog.common.CommonSureDetailDialog
import com.polaris.live.dialog.common.ConfirmCanalDetailDialog
import com.polaris.live.floating.FloatingWindowManager
import com.polaris.live.im.sfs.COMMAND_LIVE_RECOVER
import com.polaris.live.im.sfs.COMMAND_LIVE_START
import com.polaris.live.im.sfs.bean.live.LiveMsgIdMessage
import com.polaris.live.im.sfs.bean.live.LiveRoomInfo
import com.polaris.live.im.sfs.bean.live.LiveStartMessage
import com.polaris.live.im.sfs.core.SmartFoxManager
import com.polaris.live.im.sfs.core.SmartFoxQueueManager
import com.polaris.live.im.sfs.core.bean.AbstractMessage
import com.polaris.live.im.sfs.core.bean.DataArgument
import com.polaris.live.im.sfs.core.bean.ExtractMessageResponse
import com.polaris.live.im.sfs.core.bean.getRoomId
import com.polaris.live.im.sfs.core.bean.resolveExt
import com.polaris.live.im.utils.SmartFoxUtils.parseVariables
import com.polaris.live.net.homeService
import com.polaris.live.net.liveService
import com.polaris.live.popup.GlobalPopupManager
import com.polaris.live.popup.SelectVideoPopup
import com.polaris.live.resp.back_resp.LiveNoticeDontExt
import com.polaris.live.resp.back_resp.LiveScreenshotRuleBean
import com.polaris.live.resp.go_resp.MatchStartBean
import com.polaris.live.translation.R.string
import com.polaris.live.ui.live.bean.LiveInitInfo
import com.polaris.live.utils.route.RoutePath
import com.polaris.live.utils.route.Router
import com.polaris.live.utils.zego.LiveEngineManage
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import sfs2x.client.core.SFSEvent
import sfs2x.client.entities.SFSRoom
import sfs2x.client.requests.LeaveRoomRequest

/**
 * 开启直播
 *
 * @author Created by 半仙 on 2023/10/21/021 11:56
 */
object StartLiveProxy {

    /**
     * builder
     */
    fun builder(activity: AppCompatActivity): LiveStartBuilder {
        return LiveStartBuilder(activity, activity)
    }

    /**
     * builder
     */
    fun builder(fragment: Fragment): LiveStartBuilder {
        return LiveStartBuilder(fragment, fragment.requireContext())
    }

    /**
     * builder
     */
    fun builder(owner: LifecycleOwner, context: Context): LiveStartBuilder {
        return LiveStartBuilder(owner, context)
    }

    class LiveStartBuilder internal constructor(
        private val owner: LifecycleOwner,
        private val context: Context,
    ) {

        /**
         * 启动直播
         *
         * @param viewModel viewModel
         * @param liveType     直播类型
         */
        fun startLive(viewModel: BaseViewModel, @LiveType liveType: Int, success: () -> Unit = {}) {
            GlobalPopupManager.showCompletePopup(context) {
                isHavaRoom(context, viewModel) {
                    startReadyLive(owner, context, viewModel, liveType, success = success)
                }
            }
        }

        /**
         * 开启直播或者坐等
         *
         * @param viewModel viewModel
         * @param liveType     直播类型
         */
        fun startNotCheckPhotosLive(viewModel: BaseViewModel, @LiveType liveType: Int) {
            GlobalPopupManager.showCompletePopup(context) {
                isHavaRoom(context, viewModel) {
                    startReadyLive(owner, context, viewModel, liveType)
                }
            }
        }

        /**
         * 开启语言房
         *
         * @param viewModel viewModel
         * @param liveType     直播类型
         */
        fun startPartyLive(
            viewModel: BaseViewModel,
            @LiveType liveType: Int,
            theme: Int?,
            name: String? = null,
            success: () -> Unit = {},
        ) {
            GlobalPopupManager.showCompletePopup(context) {
                startReadyLive(
                    owner,
                    context,
                    viewModel,
                    liveType,
                    theme,
                    null,
                    null,
                    null,
                    name,
                    success
                )
            }
        }

        /**
         * 开启游戏派对
         *
         * @param viewModel viewModel
         * @param liveType     直播类型
         */
        fun startGamePartyLive(
            viewModel: BaseViewModel,
            @LiveType liveType: Int,
            @PartyGameType gameType: Int,
            gameAsset: Int,
            gamePrice: Long,
            name: String? = null,
            success: () -> Unit = {},
        ) {
            GlobalPopupManager.showCompletePopup(context) {
                startReadyLive(
                    owner,
                    context,
                    viewModel,
                    liveType,
                    null,
                    gameType,
                    gameAsset,
                    gamePrice,
                    name,
                    success
                )
            }
        }

        /**
         * 开启直播或者坐等并且检测用户资料弹窗
         *
         * @param viewModel viewModel
         */
        fun startSelectLive(viewModel: BaseViewModel, onlyWait: Boolean? = null) {
            XPopup.Builder(context)
                .isDestroyOnDismiss(true)
                .asCustom(SelectVideoPopup(context, onlyWait) {
                    GlobalPopupManager.showCompletePopup(context) {//判断需不需要弹出 用户完善资料
                        //区分男女去转跳
                        if (CommonUtils.isMan(UserManager.getUser().sex)) {//如果是男生
                            //判断是点的匹配还是直播  如果是匹配
                            if (it == LiveConst.Type.CLIENT_MATCH) {
                                viewModel.requestLoading({
                                    homeService.matchStart(
                                        MatchStartBean(
                                            CommonConst.MatchStart.MANUAL,
                                            UserConst.From.LIVE
                                        )
                                    )
                                }, {
                                    GlobalPopupManager.showCompletePopup(context, isOk = {
                                        Router.builder(RoutePath.LIVE_MATCH_ACTIVIYT)
                                            .withInt("page", UserConst.From.LIVE)
                                            .withInt("lastPage", UserConst.LastFrom.LIVE)
                                            .withLong("id", it.id)
                                            .navigation()
                                    })
                                })
                            } else {
                                isHavaRoom(context, viewModel) {
                                    startReadyLive(owner, context, viewModel, it)
                                }
                            }
                        } else {
                            isHavaRoom(context, viewModel) {
                                if (it == LiveConst.Type.CLIENT_MATCH) {
                                    startReadyLive(owner, context, viewModel, LiveConst.Type.ONLY_MATCH)
                                } else {
                                    startReadyLive(owner, context, viewModel, it)
                                }
                            }
                        }
                    }
                })
                .show()
        }

        private fun isHavaRoom(context: Context, viewModel: BaseViewModel, block: () -> Unit) {
            viewModel.requestLoading({ liveService.getPartyRoom() }, {
                if (it.roomId?.isNotEmpty() == true) {
                    XPopup.Builder(context)
                        .isDestroyOnDismiss(true)
                        .asCustom(
                            ConfirmCanalDetailDialog(
                                context,
                                StringUtils.getString(string.warning),
                                StringUtils.getString(string.you_have_room_is_close),
                                mConfirm = StringUtils.getString(string.confirm),
                                mCanal = StringUtils.getString(string.cancel),
                                onConfirmCallback = { block.invoke() },
                            )
                        ).show()
                } else {
                    block.invoke()
                }
            })
        }

        /**
         * 恢复直播
         *
         * @param viewModel viewModel
         */
        fun recoverLive(
            viewModel: BaseViewModel,
            liveType: Int?,
            roomId: String? = null,
            back: () -> Unit = {},
        ) {
            checkRoomState(owner) {
                startReadyLive(context, viewModel, liveType, {
                    SmartFoxQueueManager.sendLiveMessage(
                        COMMAND_LIVE_RECOVER,
                        LiveMsgIdMessage(roomId)
                    )
                }, back = back) {
                    //如果还在直播
                    if (UserManager.getUser().live?.living == AppConst.YES) {
                        viewModel.request({ liveService.liveEndState() }, {})
                    }

                    ToastGravity.showGravity(it.message)
                }
            }
        }
    }

    /**
     * 判断需不需要去封面页
     */
    private fun toSetCoverPage(liveType: Int) {
        Router.builder(RoutePath.SET_LIVE_IMAGE_ACTIVITY)
            .withInt("type", liveType)
            .withString("name", "")
            .navigation()
    }

    /**
     * 开启直播
     */
    fun startReadyLive(
        owner: LifecycleOwner,
        context: Context,
        viewModel: BaseViewModel,
        liveType: Int,
        theme: Int? = null,
        gameType: Int? = null,
        gameAsset: Int? = null,
        gamePrice: Long? = null,
        name: String? = null,
        success: () -> Unit = {},
    ) {
        checkRoomState(owner) {
            startReadyLive(context, viewModel, liveType, {
                SmartFoxQueueManager.sendLiveMessage(
                    COMMAND_LIVE_START,
                    LiveStartMessage(
                        type = liveType,
                        name = name ?: "",
                        fromType = 0,
                        theme = theme,
                        gameType = gameType,
                        gameAsset = gameAsset,
                        gamePrice = gamePrice,
                        site = if (liveType == LiveConst.Type.VIDEO_PARTY) 9 else 8
                    )
                )
            }, back = success) {
                handlerException(context, liveType, it)
            }
        }
    }

    private fun handlerException(context: Context, liveType: Int, it: Throwable) {
        if (it is AppException) {
            when (it.errCode) {
                //判断豪魅等级够不够
                CommonConst.ErrorCode.LEVEL_UNENOUGH -> {
                    XPopup.Builder(context)
                        .isDestroyOnDismiss(true)
                        .asCustom(
                            StartLiveLevelNotDialog(
                                context,
                                it.message ?: "",
                                StringUtils.getString(string.look_level),
                                0
                            )
                        )
                        .show()
                }

                CommonConst.ErrorCode.LEVEL_UNENOUGH_CHARM -> {
                    XPopup.Builder(context)
                        .isDestroyOnDismiss(true)
                        .asCustom(
                            StartLiveLevelNotDialog(
                                context,
                                it.message ?: "",
                                StringUtils.getString(string.look_charm_level),
                                1
                            )
                        )
                        .show()
                }
                //判断是否存在封面照
                CommonConst.ErrorCode.LIVE_NOT_HAVE -> {
                    toSetCoverPage(liveType)
                }
                //禁止直播弹窗
                CommonConst.ErrorCode.LIVE_DONT_START_LIVE, CommonConst.ErrorCode.LIVE_DONT_START_MATCH -> {
                    val json = it.ext?.let { JsonUtils.toJson(it) }
                    val data = json?.let { JsonUtils.fromJson<LiveNoticeDontExt>(it) }

                    val title = data?.window?.payload?.header ?: StringUtils.getString(
                        string.live_notice
                    )
                    val message = data?.window?.content ?: it.message

                    XPopup.Builder(context)
                        .isDestroyOnDismiss(true)
                        .asCustom(
                            CommonSureDetailDialog(
                                context = context,
                                mTitle = title,
                                mDetail = message,
                                mConfirmText = StringUtils.getString(string.upgrade_confirm),
                                mHighlight = data?.window?.payload?.highlight
                            )
                        ).show()
                }

                else -> {
                    ToastGravity.showGravity(it.message)
                }
            }
        } else {
            ToastGravity.showGravity(it.message)
        }

    }

    /**
     * liveType为null在恢复直播间时
     */
    private fun startReadyLive(
        context: Context,
        viewModel: BaseViewModel,
        liveType: Int?,
        success: suspend () -> ExtractMessageResponse<AbstractMessage>,
        back: () -> Unit = {},
        error: (Throwable) -> Unit,
    ) {

        when (liveType) {
            LiveConst.Type.PARTY_LIVE, LiveConst.Type.PARTY_GAME_LIVE -> {
                permissionAudio(context, {
                    startLiveGo(
                        viewModel,
                        success,
                        back,
                        error,
                        StringUtils.getString(string.start_party_loading)
                    )
                })
            }

            else -> {
                permissionVideo(context, {
                    startLiveGo(viewModel, success, back, error)
                })
            }
        }
    }

    /**
     * 真正开启直播的地方
     */
    fun startLiveGo(
        viewModel: BaseViewModel,
        success: suspend () -> ExtractMessageResponse<AbstractMessage>,
        back: () -> Unit = {},
        error: (Throwable) -> Unit,
        loadingMessage: String = StringUtils.getString(string.start_live_loading),
    ) {
        viewModel.launchLoading(loadingMessage, waitTime = 0L) {
            try {
                val liveInfo = launchLiveMessage(UserManager.getUserId(),
                    onSendCallback = {
                        success()
                    },
                    onResultCallback = {
                        val screenshotBean = it.receipt.resolveExt<LiveScreenshotRuleBean>(null)
                        getRoom()?.parseLiveInfo()?.let { variable ->
                            LiveInitInfo(variable, 0, screenshotBean?.screenshotStrategy)
                        }
                    })

                if (liveInfo != null) {
                    FloatingWindowManager.onDestroyed(liveInfo.info.type, liveInfo.info.roomId)
                    back.invoke()
                    when (liveInfo.info.type) {
                        LiveConst.Type.PARTY_LIVE -> {
                            Router.instance.setPath(RoutePath.PARTY_ANCHOR_ACTIVITY)
                                .withAny(LiveConst.Params.LIVE_INIT_INFO, liveInfo)
                                .navigation()
                        }

                        LiveConst.Type.PARTY_GAME_LIVE -> {
                            Router.instance.setPath(RoutePath.PARTY_GAME_ANCHOR_ACTIVITY)
                                .withAny(LiveConst.Params.LIVE_INIT_INFO, liveInfo)
                                .navigation()
                        }

                        LiveConst.Type.VIDEO_PARTY -> {
                            Router.instance.setPath(RoutePath.PARTY_VIDEO_ANCHOR_ACTIVITY)
                                .withAny(LiveConst.Params.LIVE_INIT_INFO, liveInfo)
                                .navigation()
                        }

                        else -> {
                            Router.instance.setPath(RoutePath.LIVE_VIDEO_ACTIVITY)
                                .withAny(LiveConst.Params.LIVE_INIT_INFO, liveInfo)
                                .navigation()
                        }
                    }
                } else {
                    throw IllegalArgumentException("Unable to parse live broadcast response information")
                }
            } catch (t: Throwable) {
                error(t)
            }
        }

    }

    //开播前检查房间状态
    fun checkRoomState(owner: LifecycleOwner, keepOnCall: () -> Unit) {
        CoroutineScopeManager.defaultScope.launch {
            LiveEngineManage.withLogin(owner, {
                keepOnCall()
            }, {
                it.printStackTrace()
                ToastGravity.showGravity(string.error_network)
            })
        }
    }

    /**
     * 发送消息并且监听，返回state
     */
    suspend fun <M : AbstractMessage> launchLiveMessageState(
        anchorId: Long,
        onSendCallback: suspend () -> ExtractMessageResponse<M>,
        onResultCallback: DataArgument.(ExtractMessageResponse<M>) -> LiveInitInfo?,
    ): ResultState<LiveInitInfo> {
        return try {
            launchLiveMessage(anchorId, onSendCallback, onResultCallback)?.let {
                ResultState.Success(it)
            } ?: ResultState.onAppError(AppException(HTTP_ERROR_CODE, "Data is null"))
        } catch (t: Throwable) {
            if (t is AppException) {
                ResultState.onAppError(t)
            } else {
                ResultState.onAppError(AppException(HTTP_ERROR_CODE, t.message))
            }
        }
    }

    /**
     * 发送消息并且监听，原始消息
     */
    suspend fun <M : AbstractMessage> launchLiveMessage(
        anchorId: Long,
        onSendCallback: suspend () -> ExtractMessageResponse<M>,
        onResultCallback: DataArgument.(ExtractMessageResponse<M>) -> LiveInitInfo?,
    ): LiveInitInfo? = coroutineScope {
        //如果上一个直播间没有退出，则先退出
        val currentRoom = SmartFoxManager.getLiveRoom()
        if (currentRoom != null) {
            val defExitRoom = async {
                SmartFoxQueueManager.eventLiveListen(SFSEvent.USER_EXIT_ROOM, timeout = 3000)
            }

            SmartFoxManager.getLiveClient()?.send(LeaveRoomRequest(currentRoom))

            try {
                defExitRoom.await()
            } catch (_: Throwable) {
            }
        }

        val listenDef = async { liveListenRoom(anchorId) }
        val joinDef = async { onSendCallback() }

        onResultCallback(listenDef.await(), joinDef.await())
    }

    private suspend fun liveListenRoom(anchorId: Long) =
        SmartFoxQueueManager.eventLiveListen(SFSEvent.ROOM_JOIN) {
            val room = it.getRoom()
            if (room != null) {
                room.getRoomId() == anchorId
            } else {
                true
            }
        }

    /**
     * 请求音视频权限
     */
    fun permissionVideo(
        context: Context,
        agreeBlock: () -> Unit,
        refuseBlock: () -> Unit = {
            ToastGravity.showGravity(string.please_open_live_permission)
        },
    ) {
        val list = listOf(
            Manifest.permission.CAMERA,
            Manifest.permission.RECORD_AUDIO
        )
        PermissionUtils.permissionGroup(
            *arrayOf(
                Manifest.permission.CAMERA,
                Manifest.permission.RECORD_AUDIO
            )
        ).callback(object : PermissionUtils.FullCallback {
            override fun onGranted(granted: MutableList<String>) {
                if (list.size != granted.size) {
                    refuseBlock()
                } else {
                    agreeBlock()
                }
            }

            override fun onDenied(
                deniedForever: MutableList<String>,
                denied: MutableList<String>,
            ) {
                CoroutineScopeManager.mainScope.launch {
                    ToastGravity.showGravity(StringUtils.getString(string.please_open_live_permission))
                }
                refuseBlock()
                showSureDetailDialog(context)
            }
        }).request()
    }

    /**
     * 请求音频权限
     */
    fun permissionAudio(
        context: Context,
        agreeBlock: () -> Unit,
        refuseBlock: () -> Unit = {
            ToastGravity.showGravity(string.please_open_live_permission)
        },
    ) {
        val list = listOf(
            Manifest.permission.RECORD_AUDIO
        )
        PermissionUtils.permissionGroup(
            *arrayOf(
                Manifest.permission.RECORD_AUDIO
            )
        ).callback(object : PermissionUtils.FullCallback {
            override fun onGranted(granted: MutableList<String>) {
                if (list.size != granted.size) {
                    refuseBlock()
                } else {
                    agreeBlock()
                }
            }

            override fun onDenied(
                deniedForever: MutableList<String>,
                denied: MutableList<String>,
            ) {
                CoroutineScopeManager.mainScope.launch {
                    ToastGravity.showGravity(StringUtils.getString(string.please_open_live_audio_permission))
                }
                refuseBlock()
                showSureDetailDialog(context)
            }
        }).request()
    }

    fun showSureDetailDialog(context: Context) {
        XPopup.Builder(context)
            .isDestroyOnDismiss(true)
            .asCustom(
                CommonSureDetailDialog(
                    context = context,
                    mTitle = StringUtils.getString(string.authorization_prompts),
                    mDetail = StringUtils.getString(string.prompts_please_open),
                    mConfirmText = StringUtils.getString(string.go_to_settings),
                    mOnSetClick = {
                        val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                        val uri = Uri.fromParts(
                            "package",
                            context.packageName,
                            null
                        )
                        intent.data = uri
                        ActivityUtils.startActivity(intent)
                    })
            ).show()

    }
}

/**
 * 将其解析为直播变量
 */
fun SFSRoom.parseLiveInfo() = parseVariables<LiveRoomInfo>()